package com.lzc.springcloud.zuul.filter;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.lzc.springcloud.zuul.config.properties.PermitURLProperties;
import com.lzc.springcloud.zuul.utils.JwtConstants;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.http.HttpServletRequestWrapper;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.RedisConnection;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.*;

import static com.lzc.springcloud.zuul.utils.JwtConstants.ANONYMOUS_USER_ID;
import static com.lzc.springcloud.zuul.utils.JwtConstants.USER_ID_IN_HEADER;

public class HeaderFilter implements Filter {

    @Autowired
    private PermitURLProperties permitURLProperties;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    private boolean isPermitUrl(String url) {
        return permitURLProperties.isPermitAllUrl(url);
    }

    private boolean isNotOAuthEndPoint(String url) {
        return !url.contains("/identity/login.html");
    }

    private boolean isJwtBearerToken(String token) {
        return StringUtils.countMatches(token, ".") == 2 && token.toLowerCase().startsWith("bearer");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
//        String authorization = request.getHeader("Authorization");
//        String requestURI = request.getRequestURI();
//
//        if (isPermitUrl(requestURI) && isNotOAuthEndPoint(requestURI)) {
//            request = new CustomHttpServletRequestWrapper(request);
//            filterChain.doFilter(request, servletResponse);
//            return;
//        }
//
//        if (StringUtils.isNotEmpty(authorization)) {
//            if (isJwtBearerToken(authorization)) {
//                authorization = StringUtils.substringBetween(authorization, ".");
//                String decodedAuth = new String(Base64.decodeBase64(authorization));
//                Map properties = new ObjectMapper().readValue(decodedAuth, Map.class);
//                String userId = (String) properties.get(USER_ID_IN_HEADER);
//                RequestContext.getCurrentContext().addZuulRequestHeader(USER_ID_IN_HEADER, userId);
//            }
//        } else {
//            RequestContext.getCurrentContext().addZuulRequestHeader(USER_ID_IN_HEADER, ANONYMOUS_USER_ID);
//        }

        filterChain.doFilter(request, servletResponse);
    }

    @Override
    public void destroy() {

    }

    private class CustomHttpServletRequestWrapper extends HttpServletRequestWrapper {

        private Set<String> headerNameSet;
        private Set<String> headerSet;

        public CustomHttpServletRequestWrapper(HttpServletRequest request) {
            super(request);
        }

        @Override
        public String getHeader(String name) {
            if ("Authorization".equalsIgnoreCase(name)) {
                return null;
            }
            if (JwtConstants.USER_ID_IN_HEADER.equalsIgnoreCase(name)) {
                return ANONYMOUS_USER_ID;
            }
            return super.getHeader(name);
        }

        @Override
        public Enumeration<String> getHeaders(String name) {
            if ("Authorization".equalsIgnoreCase(name)) {
                return Collections.emptyEnumeration();
            }
            if (USER_ID_IN_HEADER.equalsIgnoreCase(name)) {
                headerSet = new HashSet<>();
                headerSet.add(ANONYMOUS_USER_ID);
                return Collections.enumeration(headerSet);
            }
            return super.getHeaders(name);
        }

        @Override
        public Enumeration<String> getHeaderNames() {
            if (headerNameSet == null) {
                headerNameSet = new HashSet<>();
                Enumeration<String> wrappedHeaderNames = super.getHeaderNames();
                while (wrappedHeaderNames.hasMoreElements()) {
                    String headerName = wrappedHeaderNames.nextElement();
                    if (!"Authorization".equalsIgnoreCase(headerName)) {
                        headerNameSet.add(headerName);
                    }
                }
                headerNameSet.add(USER_ID_IN_HEADER);
            }
            return super.getHeaderNames();
        }
    }
}
